package com.xie.smfs.item;
//高性能物品
import com.xie.smfs.registry.ModItems;
import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.entity.damage.DamageSource;
import com.xie.smfs.damage.ModDamageSources;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Identifier;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.math.Box;
import net.minecraft.world.World;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.effect.StatusEffects;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.entity.ItemEntity;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.Formatting;
import net.minecraft.predicate.entity.EntityPredicates;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class GhostPorcelainItem extends Item {
    private static final String IS_BOUND_KEY = "IsBound";
    private static final String BOUND_PLAYER_UUID_KEY = "BoundPlayerUUID";
    public static final int BASE_DURABILITY = 200;
    private static boolean eventsRegistered = false;
    private static int tickCounter = 0; // 用于控制检查频率的计数器

    public GhostPorcelainItem(Settings settings) {
        super(settings.maxDamage(BASE_DURABILITY));
        if (!eventsRegistered) {
            registerEvents();
            eventsRegistered = true;
        }
    }

    private void registerEvents() {
        // 注册玩家受到伤害事件监听
        ServerLivingEntityEvents.ALLOW_DAMAGE.register((entity, source, amount) -> {
            if (entity instanceof PlayerEntity player && !entity.getWorld().isClient()) {
                if (isGhostDamage(source) && checkAndResistAttack(player, source, amount)) {
                    return false; // 取消伤害
                }
                if (source.isOf(RegistryKey.of(RegistryKeys.DAMAGE_TYPE, new Identifier("wither"))) && player instanceof ServerPlayerEntity serverPlayer) {
                    checkAndResistWitherEffect(serverPlayer);
                }
            }
            return true; // 允许伤害
        });

        // 注册掉落物被火烧的事件监听
        ServerTickEvents.END_SERVER_TICK.register(server -> {
            tickCounter++;
            // 每20 tick(1秒)执行一次检查，减少性能消耗
            if (tickCounter % 20 == 0) {
                for (ServerWorld world : server.getWorlds()) {
                    checkBurningGhostPorcelainItems(world);
                }
                tickCounter = 0;
            }
        });
    }

    /**
     * 检查世界中正在燃烧的鬼瓷掉落物
     */
    private void checkBurningGhostPorcelainItems(ServerWorld world) {
        // 使用正确的 getEntitiesByClass 方法，包含3个参数
        // 优化搜索范围：只搜索所有玩家周围32格范围内的实体
        List<ItemEntity> itemEntities = new ArrayList<>();
        for (PlayerEntity player : world.getPlayers()) {
            BlockPos playerPos = player.getBlockPos();
            Box searchBox = new Box(
                playerPos.getX() - 32, playerPos.getY() - 32, playerPos.getZ() -32,
                playerPos.getX() +32, playerPos.getY() +32, playerPos.getZ() +32
            );
            itemEntities.addAll(world.getEntitiesByClass(
                ItemEntity.class,
                searchBox,
                entity -> EntityPredicates.VALID_ENTITY.test(entity) && 
                       entity.getStack().isOf(ModItems.GHOST_PORCELAIN) && 
                       isBound(entity.getStack())
            ));
        }

        for (ItemEntity itemEntity : itemEntities) {
            ItemStack stack = itemEntity.getStack();
            // 已经在筛选条件中确认过是鬼瓷且已绑定，直接检查燃烧状态
            if (isItemEntityOnFire(itemEntity)) {
                handleGhostPorcelainBurning(stack, world, itemEntity);
            }
        }
    }

    /**
     * 检查掉落物是否在火中
     */
    private boolean isItemEntityOnFire(ItemEntity itemEntity) {
        BlockPos pos = itemEntity.getBlockPos();
        World world = itemEntity.getWorld();

        // 检查掉落物是否在火方块上
        BlockState blockState = world.getBlockState(pos);
        if (blockState.isOf(Blocks.FIRE) || blockState.isOf(Blocks.SOUL_FIRE)) {
            return true;
        }

        // 检查掉落物是否在熔岩中
        if (itemEntity.isInLava()) {
            return true;
        }

        // 检查掉落物是否着火了
        if (itemEntity.isOnFire()) {
            return true;
        }

        // 检查掉落物下方的方块是否是火源
        BlockPos belowPos = pos.down();
        BlockState belowState = world.getBlockState(belowPos);
        return belowState.isOf(Blocks.FIRE) || belowState.isOf(Blocks.SOUL_FIRE) ||
                belowState.isOf(Blocks.MAGMA_BLOCK) || belowState.isOf(Blocks.CAMPFIRE) ||
                belowState.isOf(Blocks.SOUL_CAMPFIRE);
    }

    /**
     * 处理鬼瓷被火烧的情况
     */
    private void handleGhostPorcelainBurning(ItemStack stack, World world, ItemEntity itemEntity) {
        NbtCompound nbt = stack.getNbt();
        if (nbt != null && nbt.containsUuid(BOUND_PLAYER_UUID_KEY)) {
            UUID boundPlayerUuid = nbt.getUuid(BOUND_PLAYER_UUID_KEY);

            // 杀死绑定的玩家
            killBoundPlayer(boundPlayerUuid, world);

            // 销毁物品
            itemEntity.setStack(ItemStack.EMPTY);
            itemEntity.discard();

            // 播放玻璃碎掉的声音
            if (!world.isClient) {
                world.playSound(
                        null, // 没有特定的播放者
                        itemEntity.getBlockPos(), // 声音位置
                        SoundEvents.BLOCK_GLASS_BREAK, // 玻璃破碎音效
                        SoundCategory.BLOCKS, // 方块音效类别
                        1.0f, // 音量
                        1.0f // 音调
                );
            }
        }
    }

    private boolean isGhostDamage(DamageSource source) {
        return source.isOf(ModDamageSources.GHOST);
    }

    private boolean checkAndResistAttack(PlayerEntity player, DamageSource source, float amount) {
        for (ItemStack stack : player.getInventory().main) {
            if (stack.isOf(ModItems.GHOST_PORCELAIN) && isBound(stack)) {
                if (tryResistAttack(player, amount, stack, source)) {
                    return true;
                }
            }
        }
        return checkOffHandAttack(player, source, amount);
    }

    private boolean checkOffHandAttack(PlayerEntity player, DamageSource source, float amount) {
        ItemStack offHandStack = player.getOffHandStack();
        if (offHandStack.isOf(ModItems.GHOST_PORCELAIN) && isBound(offHandStack)) {
            return tryResistAttack(player, amount, offHandStack, source);
        }
        return false;
    }

    private static void damageItem(ItemStack stack, int amount, PlayerEntity player) {
        stack.damage(amount, player, p -> p.sendToolBreakStatus(Hand.MAIN_HAND));

        if (stack.getDamage() >= stack.getMaxDamage()) {
            NbtCompound nbt = stack.getNbt();
            if (nbt != null && nbt.containsUuid(BOUND_PLAYER_UUID_KEY)) {
                UUID boundPlayerUuid = nbt.getUuid(BOUND_PLAYER_UUID_KEY);
                killBoundPlayer(boundPlayerUuid, player.getWorld());
            }
        }
    }

    private void checkAndResistWitherEffect(ServerPlayerEntity player) {
        StatusEffectInstance witherEffect = player.getStatusEffect(StatusEffects.WITHER);
        if (witherEffect != null) {
            boolean mainInventoryResisted = false;
            for (ItemStack stack : player.getInventory().main) {
                if (removeWitherEffect(player, stack)) {
                    mainInventoryResisted = true;
                    break;
                }
            }
            if (mainInventoryResisted || removeWitherEffect(player, player.getOffHandStack())) {
                player.removeStatusEffect(StatusEffects.WITHER);
            }
        }
    }

    private boolean removeWitherEffect(ServerPlayerEntity player, ItemStack stack) {
        if (stack.isOf(ModItems.GHOST_PORCELAIN) && isBound(stack)) {
            damageItem(stack, 1, player);
            return true;
        }
        return false;
    }

    @Override
    public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
        ItemStack stack = user.getStackInHand(hand);
        if (!world.isClient) {
            if (isBound(stack)) {
                unbindPlayer(stack);
                user.sendMessage(Text.translatable("item.smfs.ghost_porcelain.unbound"), true);
                return TypedActionResult.success(stack);
            } else {
                return bindPlayerIfHealthAllows(user, stack);
            }
        }
        return TypedActionResult.pass(stack);
    }

    private TypedActionResult<ItemStack> bindPlayerIfHealthAllows(PlayerEntity user, ItemStack stack) {
        if (user.getHealth() > 4) {
            user.setHealth(user.getHealth() - 4);
            bindPlayer(stack, user);
            user.sendMessage(Text.translatable("item.smfs.ghost_porcelain.bound"), true);
            return TypedActionResult.success(stack);
        } else {
            user.sendMessage(Text.translatable("item.smfs.ghost_porcelain.not_enough_health"), true);
        }
        return TypedActionResult.pass(stack);
    }

    public static boolean isBound(ItemStack stack) {
        NbtCompound nbt = stack.getNbt();
        return nbt != null && nbt.getBoolean(IS_BOUND_KEY);
    }

    private void bindPlayer(ItemStack stack, PlayerEntity player) {
        unbindAllPlayersGhostPorcelain(player);
        NbtCompound nbt = stack.getOrCreateNbt();
        nbt.putBoolean(IS_BOUND_KEY, true);
        nbt.putUuid(BOUND_PLAYER_UUID_KEY, player.getUuid());
    }

    private void unbindAllPlayersGhostPorcelain(PlayerEntity player) {
        for (int i = 0; i < player.getInventory().size(); i++) {
            ItemStack invStack = player.getInventory().getStack(i);
            if (invStack.isOf(ModItems.GHOST_PORCELAIN) && isBound(invStack)) {
                unbindPlayer(invStack);
            }
        }
    }

    private void unbindPlayer(ItemStack stack) {
        NbtCompound nbt = stack.getOrCreateNbt();
        nbt.remove(IS_BOUND_KEY);
        nbt.remove(BOUND_PLAYER_UUID_KEY);
    }

    @Override
    public void appendTooltip(ItemStack stack, World world, List<Text> tooltip, TooltipContext context) {
        super.appendTooltip(stack, world, tooltip, context);
        if (isBound(stack)) {
            tooltip.add(Text.translatable("item.smfs.ghost_porcelain.bound_status"));
            NbtCompound nbt = stack.getNbt();
            if (nbt != null && nbt.containsUuid(BOUND_PLAYER_UUID_KEY)) {
                UUID uuid = nbt.getUuid(BOUND_PLAYER_UUID_KEY);
                tooltip.add(Text.translatable("item.smfs.ghost_porcelain.bound_to", uuid.toString().substring(0, 8)));
            }
        } else {
            tooltip.add(Text.translatable("item.smfs.ghost_porcelain.unbound_status"));
        }

        // 添加火烧警告提示
        tooltip.add(Text.translatable("item.smfs.ghost_porcelain.fire_warning").formatted(Formatting.RED));
    }

    public static boolean tryResistAttack(PlayerEntity player, float damageAmount, ItemStack stack, DamageSource source) {
        if (stack.isOf(ModItems.GHOST_PORCELAIN) && isBound(stack)) {
            int durabilityToConsume = Math.max(1, (int)Math.ceil(damageAmount * 0.8));
            damageItem(stack, durabilityToConsume, player);
            return true;
        }
        return false;
    }

    private static void killBoundPlayer(UUID boundPlayerUuid, World world) {
        if (boundPlayerUuid == null) {
            return;
        }
        PlayerEntity player = world.getPlayerByUuid(boundPlayerUuid);
        if (player != null) {
            DamageSource damageSource = ModDamageSources.of(world, ModDamageSources.GHOST);
            player.damage(damageSource, Float.MAX_VALUE);

            // 发送死亡消息
            if (!world.isClient) {
                player.sendMessage(Text.translatable("item.smfs.ghost_porcelain.burned_death").formatted(Formatting.DARK_RED), false);
            }
        }
    }
}